home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cuj9205.zip / CMENU13.EXE / RMENU2.C < prev    next >
C/C++ Source or Header  |  1992-04-01  |  8KB  |  387 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu2.c
  4.  *    Top-level menu processing
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #include "cmenu.h"
  9. #include "rcmenu.h"
  10.  
  11. #if __STDC
  12. #pragma hdrstop
  13. #endif
  14.  
  15. #include <ctype.h>
  16.  
  17.  
  18. /************************************************************
  19.  * sub_menu(): 
  20.  *    Run a local menu at the given nesting level
  21.  *    Default command/menu path is supplied via "path".
  22.  ************************************************************/
  23.  
  24. int sub_menu(mnum, path)
  25. int mnum;
  26. char *path;
  27. {
  28.     MENU2 *M2p = LMenus[nestlev].Menus[mnum];
  29.     MENU *Mp = &M2p -> Menu;
  30.     char newpath[MAX_PATH];
  31.     
  32.     int cur_item = 0;
  33.     int sel_val = 0;
  34.     int factor;
  35.     
  36.     draw_menu(M2p, cur_item);        /* display the menu        */
  37.  
  38.     strcpy(newpath, make_path(path, Mp -> path));
  39.  
  40.     while (1)
  41.     {
  42.         switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
  43.         {
  44.             case  KEY_UP:
  45.                 draw_item(M2p, cur_item, NORMAL, NO);
  46.                 cur_item = cur_item ? cur_item - 1 :
  47.                         Mp -> nitems - 1;
  48.                 draw_item(M2p, cur_item, STANDOUT, YES);
  49.                 break;
  50.                 
  51.             case KEY_DOWN:
  52.                 draw_item(M2p, cur_item, NORMAL, NO);
  53.                 cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
  54.                         cur_item + 1;
  55.                 draw_item(M2p, cur_item, STANDOUT, YES);
  56.                 break;
  57.  
  58.             case KEY_RIGHT:
  59.                 if (Mp -> columns == 1)
  60.                     break;
  61.  
  62.                 draw_item(M2p, cur_item, NORMAL, NO);
  63.  
  64.                 factor = MAX_IROWS / Mp -> spacing;
  65.                 if (cur_item + factor < Mp -> nitems)
  66.                     cur_item += factor;
  67.                 else
  68.                     cur_item %= factor;
  69.  
  70.                 draw_item(M2p, cur_item, STANDOUT, YES);
  71.                 break;
  72.                 
  73.             case KEY_LEFT:
  74.                 if (Mp -> columns == 1)
  75.                     break;
  76.                 draw_item(M2p, cur_item, NORMAL, NO);
  77.  
  78.                 factor = MAX_IROWS / Mp -> spacing;
  79.                 if (cur_item >= factor)
  80.                     cur_item -= factor;
  81.                 else
  82.                     while (cur_item + factor < Mp -> nitems)
  83.                         cur_item += factor;
  84.  
  85.                 draw_item(M2p, cur_item, STANDOUT, YES);
  86.                 break;
  87.                 
  88.             case KEY_SHOW:
  89.                 show_item(M2p, cur_item, newpath);
  90.                 break;
  91.                 
  92.             case KEY_RUN:
  93.                 if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
  94.                     return OK;
  95.                 if (do_item(M2p, cur_item, newpath) == EXITALL)
  96.                     return EXITALL;
  97.  
  98.                 switch(M2p -> Items[cur_item] -> nextcode)
  99.                 {
  100.                     case NXT_FIRST:
  101.                         cur_item = 0;
  102.                         break;
  103.                         
  104.                     case NXT_LAST:
  105.                         cur_item = M2p -> Menu.nitems - 1;
  106.                         break;
  107.                     
  108.                     case NXT_NEXT:
  109.                         if (cur_item < M2p -> Menu.nitems - 1)
  110.                             cur_item++;
  111.                         break;
  112.                         
  113.                     case NXT_DIRECT:
  114.                         cur_item = M2p -> Items[cur_item] -> nextitem;
  115.                         break;
  116.                 }
  117.  
  118.                 draw_menu(M2p, cur_item);   /* redisplay menu */
  119.                 break;
  120.                 
  121.             case K_DIRECT:
  122.                 if ((sel_val - 1) != cur_item)
  123.                 {
  124.                     draw_item(M2p, cur_item, NORMAL, NO);
  125.                     cur_item = sel_val - 1;
  126.                     draw_item(M2p, cur_item, STANDOUT, YES);
  127.                 }
  128.                 break;
  129.  
  130.             case K_SHELL:
  131.                 if (M2p -> Menu.escape == YES ||
  132.                   (M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
  133.                 {
  134. #if SHELL_PROMPT
  135.                     if (put_msg(0, SH_PROMPT_STR) == ESC)
  136.                         break;
  137. #else
  138.                     move(ERR_ROW, 0);
  139.                     hlight_on();
  140.                     addstr("Invoking shell. . .");
  141.                     hlight_end();
  142. #endif
  143.  
  144.                     pre_shell();        /* set up for shell call    */
  145.                     system(SysShell);    /* run a shell                */
  146.                     post_shell();        /* restore everything        */
  147.  
  148.                     draw_menu(M2p, cur_item);
  149.                 }
  150.                 else
  151.                   put_msg(1, "Sorry, shell escapes are disabled.");
  152.                 break;
  153.  
  154.             case K_EXIT:
  155.                 return OK;
  156.  
  157.             case K_EXITALL:
  158.                 return EXITALL;
  159.  
  160.             case K_VERSION:
  161.                 put_msg(0, " RMENU Menu Interpreter v%s ",
  162.                              VERSION);
  163.                 break;
  164.  
  165.             case K_UNKNOWN:
  166.                 beep();
  167.         }
  168.         refresh();
  169.     }
  170. }
  171.  
  172.  
  173. /************************************************************
  174.  * draw_menu(): 
  175.  *    Display the entire menu, including all prompts,
  176.  *    and titles and help text (if any) for current item
  177.  *    on the screen.
  178.  ************************************************************/
  179.  
  180. Void draw_menu(M2p, curr)
  181. MENU2 *M2p;
  182. int curr;
  183. {
  184.     MENU *Mp = &M2p -> Menu;
  185.     int title_len = strlen(Mp -> title);
  186.     int i, j; 
  187.     
  188.     clear();
  189.  
  190.     move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
  191.     addstr(Mp -> title);    /* Put up menu title */
  192.  
  193.     for (i = 0; i < Mp -> nitems; i++)
  194.         if (i != curr)
  195.             draw_item(M2p, i, NORMAL, NO);
  196.  
  197.     draw_item(M2p, curr, STANDOUT, YES);
  198.  
  199.     move(PROMPT_ROW, 0);
  200.     addstr(MENU_OPTS);
  201.     if (Mp -> escape == YES ||
  202.             (Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
  203.         addstr(MENU_SHELL);
  204.     addstr(MENU_PROMPT);
  205.     getyx(stdscr, echoy, echox);    /* save coords of item # echo area */
  206.         
  207.     refresh();    /* display the window */
  208.  
  209. }
  210.  
  211.  
  212. /************************************************************
  213.  * draw_item():
  214.  *    Display a single item (the current item) of the
  215.  *    specified menu, using the specified video mode.
  216.  *    Display assiciated help text only if "dohelp"
  217.  *    is TRUE.
  218.  ************************************************************/
  219.  
  220. Void draw_item(M2p, item, vid_mode, dohelp)
  221. MENU2 *M2p;
  222. int item, vid_mode, dohelp;
  223. {
  224.     ITEM *Ip = M2p -> Items[item];
  225.     COORDS *Cp = &M2p -> coords[item];
  226.     int j;
  227.     int help_len;
  228.  
  229.     move (Cp->ypos, Cp->xpos);
  230.     printw("%2d.", item + 1);
  231.  
  232.     if (vid_mode == STANDOUT)
  233.         hlight_on();
  234.  
  235.     printw(" %s", Ip -> text);
  236.  
  237.     for (j = 0; j < Cp -> spaces_needed; j++)
  238.             addch(' ');
  239.  
  240.     if (vid_mode == STANDOUT)
  241.         hlight_end();
  242.  
  243.  
  244.     if (dohelp == YES)
  245.     {
  246.         move(HELP_ROW0, HELP_COL0);
  247.         if (*Ip -> help)
  248.         {
  249.             addstr(" HELP: ");    /* display "HELP:" text    */
  250.  
  251.             move (HELP_ROW, 0);    /* Erase preivous help text (if any) */
  252.             clrtoeol();
  253.  
  254.             help_len = strlen(Ip -> help);
  255.             if (help_len > (SCREEN_COLS - 6))
  256.                 move (HELP_ROW, (80 - strlen(Ip -> help))/2);
  257.             else
  258.                 move (HELP_ROW, (80 - help_len)/2 - 2);
  259.  
  260.             hlight_on();
  261.             if (help_len <= (SCREEN_COLS - 6))
  262.                 addstr(" ");
  263.             addstr(Ip -> help);
  264.             if (help_len <= (SCREEN_COLS - 6))
  265.                 addstr(" ");
  266.             hlight_end();
  267.             clrtoeol();
  268.         }
  269.         else
  270.         {
  271.             addstr("       ");    /* clear help text area    */
  272.             move(HELP_ROW, 0);
  273.         }
  274.         clrtoeol();
  275.     }
  276. }
  277.  
  278.  
  279. /************************************************************
  280.  * get_cmd()
  281.  *    Get a command from the user.
  282.  *    Arrow keys or space returns the appropriate K_ code.
  283.  *    Pressing Enter returns the K_RUN code.
  284.  *    Pressing ! returns the K_SHELL code.
  285.  *    Entering a direct number returns K_DIRECT,
  286.  *    and the sel_val is set (indirectly) to selection number
  287.  *  (1-based).
  288.  ************************************************************/
  289.  
  290. int get_cmd(nitems, curr, sel_val)
  291. int nitems;
  292. int curr;
  293. int *sel_val;
  294. {
  295.     int ch;
  296.     int newval;
  297.     int savy, savx;
  298.  
  299.     static int digits = FALSE;    /* true if digits being entered */
  300.     
  301.     move(echoy, echox);    /* move to prompt location */
  302.     printw("%d", curr + 1);
  303.     getyx(stdscr, savy, savx);
  304.     clrtoeol();
  305.     move(savy, savx);
  306.     refresh();
  307.     
  308.     while (1)
  309.     {
  310.         ch = getch();
  311.         if (!isdigit(ch))
  312.             digits = FALSE;
  313.         switch (ch)
  314.         {
  315.             case KEY_UP:
  316.             case '\b':        /* WYSE 60s send this for left arrow */
  317.                 clrtoeol();
  318.                 return KEY_UP;
  319.  
  320.             case ' ':
  321.             case KEY_DOWN:
  322. #if UNIX || XENIX
  323.             case '\n':        /* WYSE 60s send this for down arrow */
  324. #endif
  325.                 clrtoeol();
  326.                 return KEY_DOWN;
  327.  
  328.             case KEY_RIGHT:
  329.             case KEY_LEFT:
  330.             case KEY_RUN:
  331.             case KEY_SHOW:
  332.                 return ch;
  333.  
  334.             case 'e':
  335.             case 'E':
  336.                 return K_EXIT;
  337.  
  338.             case 'x':
  339.             case 'X':
  340.                 return K_EXITALL;
  341.                 
  342.             case 'v':
  343.             case 'V':
  344.                 return K_VERSION;
  345.  
  346.             case '!':
  347.                 return K_SHELL;
  348.  
  349.             case ESC:        /* clear digits area */
  350.                 digits = FALSE;
  351.                 move(echoy, echox);    
  352.                 clrtoeol();
  353.                 refresh();
  354.                 break;
  355.                 
  356.             default:        /* handle digits */
  357.                 if (!isdigit(ch))
  358.                     return K_UNKNOWN;
  359.  
  360.                 if (digits && 
  361.                     (newval = *sel_val * 10 + (ch - '0')) <= nitems
  362.                         && newval > 0)
  363.                 {
  364.                     addch(ch);
  365.                     refresh();
  366.                     *sel_val = newval;
  367.                     return K_DIRECT;
  368.                 }
  369.                 else if ( (newval = ch - '0') && newval <= nitems)
  370.                 {
  371.                     digits = TRUE;
  372.                     move(echoy, echox);    
  373.                     addch(ch);
  374.                     clrtoeol();
  375.                     refresh();
  376.                     *sel_val = newval;
  377.                     return K_DIRECT;
  378.                 }
  379.                 else
  380.                 {
  381.                     digits = FALSE;
  382.                     beep();
  383.                 }
  384.         }
  385.     }
  386. }
  387.